#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/5/17 13:56
# @Author  : Grayson Liu
# @Email   : graysonliu@foxmail.com
# @File    : jvm2008.py

import re
from typing import Union
import pandas as pd


def company_rule(x: str) -> str:
    """
    对Company这一列数据的处理操作，用于DataFrame的map方法
    :param x: Company属性的值
    :return: 处理后的值
    """
    y = x.replace(",", "")  # 去除逗号
    y = re.sub(r"\bCo$", "Corporation", y)  # 正则表达式替换：\b匹配单词边界，$匹配字符串末尾
    return y


def processor_rule(x: str) -> str:
    """
    对Processor这一列数据的处理操作，用于DataFrame的map方法
    :param x: Processor属性的值
    :return: 处理后的值
    """
    y = re.sub(r"\(.*\)", "", x)  # 删除括号中的内容
    y = y.replace("Quad Core", "")  # 删除”Quad Core“
    y = y.rstrip()  # 处理删除之后，末尾留下的空格
    return y


def cpu_speed_rule(x: Union[int, float]) -> int:
    """
    对CPU Speed这一列数据的处理操作，用于DataFrame的map方法
    :param x: CPU Speed属性的值
    :return: 处理后的CPU Speed(MHz)值
    """
    return int(x if x > 10 else 1000 * x)  # 统一单位为MHz，对单位是GHz的（数值小于10），乘以1000


def first_cache_rule(x: str) -> str:
    """
    对1st Cache这一列数据的处理操作，用于DataFrame的map方法
    :param x: 1st Cache属性的值
    :return: 处理后的1st Cache per core(KB)值
    """
    if x.find("per core") != -1:
        # 说明：(group1: 1个以上数字)+'KB'+可能有空格+'(I)'或'I'+可能有空格+'+'+可能有空格+(group2: 1个以上数字)+'KB'+可能有空格+'(D)'或'D'
        search_obj = re.match(r"(\d+)KB\s*(?:\(I\)|I)\s*\+\s*(\d+)KB\s*(?:\(D\)|D)", x)
        l1i_kb = search_obj.group(1)
        l1d_kb = search_obj.group(2)
        return f"{l1i_kb}KB(I)+{l1d_kb}KB(D)"
    else:
        # 说明：(group1: 1个以上数字)+可能有空格+'KB'
        search_obj = re.match(r"(\d+)\s*KB", x)
        l1_kb = search_obj.group(1)
        return f"{l1_kb}KB(I+D)"


def second_cache_rule(line: pd.Series) -> str:
    """
    对2nd Cache这一列数据的处理操作，用于DataFrame的apply方法（需要用到其他属性的值）
    :param line: DataFrame的一行，类型是pd.Series
    :return: 处理后的2nd Cache per core(KB)值
    """
    x = line["2nd Cache"]
    cores_per_chip = line["# cores per chip"]
    cores_num = line["# cores"]
    if x.find("per core") != -1:
        search_obj = re.match(r"(\d+)\s*KB", x)
        l2_kb = search_obj.group(1)
        return f"{l2_kb}KB"
    elif x.find("per chip") != -1:
        search_obj = re.match(r"(\d+)\s*MB", x)
        l2_kb = int((int(search_obj.group(1)) * 1024) / cores_per_chip)
        return f"{l2_kb}KB"
    elif x.find("shared per 2 cores") != -1:
        search_obj = re.match(r"(\d+)\s*MB", x)
        l2_kb = int((int(search_obj.group(1)) * 1024) / cores_per_chip)
        return f"{l2_kb}KB"
    else:
        if x.find("MB") != -1:
            search_obj = re.match(r"(\d+)\s*MB", x)
            l2_kb = int((int(search_obj.group(1)) * 1024) / cores_num)
            return f"{l2_kb}KB"
        else:
            search_obj = re.match(r"(\d+)\s*KB", x)
            return f"{search_obj.group(1)}KB"


def third_cache_rule(x: Union[str, float]) -> str:
    """
    对Other Cache这一列数据的处理操作，用于DataFrame的map方法
    :param x: 1st Cache属性的值由于数据可能是缺失值（即NaN，float型）也可能是字符串
    :return: 处理后的3rd Cache per chip(MB)值
    """
    if type(x) == str:
        if x.find("L3") != -1:
            search_obj = re.match(r"(\d+)\s*MB", x)
            return f"{search_obj.group(1)}MB"
        else:
            return "0"
    else:
        return "0"


def other_cache_rule(x: Union[str, float]) -> str:
    """
    对Other Cache这一列数据的处理操作，用于DataFrame的map方法
    :param x: 1st Cache属性的值由于数据可能是缺失值（即NaN，float型）也可能是字符串
    :return: 处理后的Other Cache per chip(MB)值
    """
    if type(x) == str:
        if x.find("L3") == -1 and x.find("MB") != -1:
            search_obj = re.match(r"(\d+)\s*MB", x)
            return f"{search_obj.group(1)}MB"
        else:
            return "0"
    else:
        return "0"


def memory_rule(x: str) -> str:
    """
    对Memory这一列数据的处理操作，用于DataFrame的map方法
    :param x: Memory属性的值
    :return: 处理后的Memory(GB)值
    """
    if x.find("MB") != -1:
        search_obj = re.match(r"(\d+)\s*MB", x)
        memory_gb = int(int(search_obj.group(1)) / 1024)
        return f"{memory_gb}GB"
    elif x.find("GB") != -1:
        search_obj = re.match(r"(\d+)\s*GB", x)
        return f"{search_obj.group(1)}GB"
    else:
        return f"{int(int(x) / 1024)}GB"


def report_link_rule(x: str) -> str:
    """
    对Disclosure这一列数据的处理操作，用于DataFrame的map方法
    :param x: Disclosure属性的值
    :return: 处理后的Report Link值
    """
    search_obj = re.match(r'<A HREF="(.*)">HTML</A>', x)
    return f"https://www.spec.org{search_obj.group(1)}"
